<?php
define('CMSPAD_VERSION', '1.3.3.v20081019');
if(!defined('CMSPAD_DEBUG')){
	define('CMSPAD_DEBUG',false);
}
if(CMSPAD_DEBUG == true){
	ini_set('expose_php', 'on');
	ini_set('display_errors','on');
	error_reporting(E_ALL);
}else{
	ini_set('expose_php', 'off');
	ini_set('display_errors','off');
	error_reporting(E_ERROR);
}

$CMSPAD_CONSTANTS = array();
/**
 * CMSPAD_ABSPATH: The absolute path of web application. E:\php\CMSPATH\
 */
if(!defined('CMSPAD_ABSPATH')){
	define('CMSPAD_ABSPATH',str_replace('\\','/',__FILE__?dirname(__FILE__) . '/':'./'));
}
$CMSPAD_CONSTANTS['CMSPAD_ABSPATH'] = CMSPAD_ABSPATH;

/**
 * CMSPAD_RELPATH: The relataive path of web application. /CMSPATH/
 */
if(!defined('CMSPAD_RELPATH')){
	$documentRoot = $_SERVER['DOCUMENT_ROOT'];
	$drLen = strlen($documentRoot);
	$dpLen = strlen(__FILE__);
	$dbLen = strlen(basename(__FILE__));
	define('CMSPAD_RELPATH',str_replace('\\','/',substr(__FILE__,$drLen,$dpLen - $drLen - $dbLen)));
}
$CMSPAD_CONSTANTS['CMSPAD_RELPATH'] = CMSPAD_RELPATH;

/**
 * Get class name
 * <p>It supports the class name which was obfuscated by zend guard.</p>
 *
 * @param string $class Class name
 * @return string Real class name.
 */
function cmspad_get_class_name($class){
	static $zend_c_exists;
	if(!isset($zend_c_exists)){
		$zend_c_exists = function_exists('Zend_obfuscate_class_name');
	}
	
	if(is_object($class)){
		return get_class($class);
	}
	
	if(!class_exists($class)){
		if($zend_c_exists){
			$className = Zend_obfuscate_class_name($class);
			if(class_exists($className)){
				return $className;
			}
		}
	}else{
		return $class;
	}
	
	return false;
}

/**
 * Get function name
 * <p>It supports the class name which was obfuscated by zend guard.</p>
 *
 * @param string $class Class name
 * @return string Real class name.
 */
function cmspad_get_function_name($name,$class = null){
	static $zend_f_exists;
	if(!isset($zend_f_exists)){
		$zend_f_exists = function_exists('Zend_obfuscate_function_name');
	}
	
	$class = $class?cmspad_get_class_name($class):null;
	$functionExists = $class?method_exists($class,$name):function_exists($name);
	if(!$functionExists){
		if($zend_f_exists){
			$name = Zend_obfuscate_function_name($name);
			if($name){
				$functionExists = $class?method_exists($class,$name):function_exists($name);
				if($functionExists){
					return $name;
				}
			}
		}
	}else{
		return $name;
	}
	
	return false;
}

/**
 * Includes the class passed as parameter to allow be used by the application.
 * <p>e.g. cmspad.JSPacker directs to  inc/cmspad/JSPacker.php</p>
 * <p>e.g. example:some.Clazz directs to  <code>CMSPAD_PORTLET_ABSPATH/example/inc/some/Clazz.php</code></p>
 *
 * @param string $classpath the class name. e.g. cmspad.JSPacker or example:some.Clazz
 * @version 1.0.20070919 Add Zend obfuscated class name checking.
 */
function cmspad_import($classPath){
	
	if(($pos = strpos($classPath,':')) !== false){
		$portlet = trim(substr($classPath,0,$pos));
		$classPath = trim(substr($classPath,$pos + 1));
	}else{
		$portlet = false;
	}
	
	$includedFiles = get_included_files();
	$parts = explode('.',$classPath);
	
	if(array_pop($parts) == '*'){
		
		$files = array();
		
		$packagePath = implode('/',$parts);
		
		{ // Search system's inc directory.
			if($portlet){
				$classpath = CMSPAD_PORTLET_ABSPATH . $portlet . '/inc/' . $packagePath;
			}else{
				$classpath = CMSPAD_ABSPATH . 'inc/' . $packagePath;
			}
			if(is_dir($classpath)){
				$path = $classpath;
			}else{
				$path = $packagePath;
			}
			$dir = opendir($path);
			while(($file = readdir($dir)) != false){
				if(substr($file,-10) == '.php'){
					if(file_exists($filePath)){
						$filePath = explode('.',$path);
						array_push($filePath,$file);
						$filePath = implode('/',$filePath);
						if(!in_array($filePath,$includedFiles)){
							require_once ($filePath);
							$className = cmspad_get_class_name(basename($filePath,'.php'));
							if(!$className){
								continue;
							}
							array_push($filePath,$className);
						}
					}
				}
			}
			closedir($dir);
		}
		return $files;
	}else{
		$importFileName = str_replace('.','/',$classPath) . '.php';
		if($portlet){
			$importSysFile = CMSPAD_PORTLET_ABSPATH . $portlet . '/inc/' . $importFileName;
		}else{
			$importSysFile = CMSPAD_ABSPATH . 'inc/' . $importFileName;
		}
		if(file_exists($importSysFile)){
			if(!in_array($importSysFile,$includedFiles)){
				require_once ($importSysFile);
				$className = cmspad_get_class_name(basename($importSysFile,'.php'));
				if($className){
					return $className;
				}
			}else{
				return cmspad_get_class_name(basename($importSysFile,'.php'));
			}
		}
		return false;
	}
}

/**
 * Normalize relative path to absolute path.
 * <p>For example, this function can convert <code>hello/world/../hehe/./wasai/../../haha/</code> to <code>hello/haha/</code></p>
 *
 * @param string $relative
 * @return string
 */
function cmspad_normalize_path($relative){
	$relative = str_replace('\\','/',$relative);
	if(strpos($relative,'./') !== false){
		$pathStack = explode('/',$relative);
		$pathArray = array();
		while(!empty($pathStack)){
			$path = trim(array_shift($pathStack));
			switch($path){
				case '.':
					break;
				case '..':
					if(!empty($pathArray)){
						array_pop($pathArray);
					}
					break;
				default:
					if(!empty($path)){
						$pathArray[] = $path;
					}
					break;
			}
		}
		$path = implode('/',$pathArray);
		if(substr($relative,0,1) == '/'){
			$path = '/' . $path;
		}
		if(substr($relative,-1) == '/'){
			$path .= '/';
		}
		while(strpos($path, '//') !== false){
			$path = str_replace('//', '/', $path);
		}
		return $path;
	}else{
		return $relative;
	}
}

/**
 * Convert absolute path under document root to relative path.
 * <p>For example, 
 * if the document root is '/var/www/', 
 * then this function converts the path '/var/www/example/hello.php' to '/example/hello.php'</p>
 * 
 * @param string $file absolute path.
 * @return string relative path.
 */
function cmspad_absolute2relative($file){
	$documentRoot = str_replace('\\','/',$_SERVER['DOCUMENT_ROOT']);
	$documentFile = str_replace('\\','/',$file);
	if(strpos($documentRoot,$documentFile) == 0){
		return cmspad_normalize_path(substr($documentFile,strlen($documentRoot)));
	}else{
		return false;
	}
}

/**
 * Convert relative path to absolute path.
 * <p>For example, 
 * if the document root is '/var/www/', 
 * then this function converts the path '/example/hello.php' to '/var/www/example/hello.php'</p>
 *
 * @param string $path relative path.
 * @return string absolute path.
 */
function cmspad_relative2absolute($path){
	$documentRoot = $_SERVER['DOCUMENT_ROOT'];
	if(substr($path,0) == '/'){
		// Convert document root path.
		$path = $documentRoot . str_replace('\\','/',$path);
	}else{
		// Convert current file path.
		$currentDir = str_replace('\\','/',dirname($_SERVER["SCRIPT_NAME"]));
		$path = $documentRoot . $currentDir . '/' . $path;
	}
	return cmspad_normalize_path($path);
}

/**
 * Convert sub relative path to full relative path.
 * <p>For example, 
 * if current file relative path is '/hello/world/test.php', 
 * then this function converts the path '../hello.php' to '/hello/hello.php'</p>
 *
 * @param string $path the sub relative path
 * @return string the document root based path.
 */
function cmspad_relative2relative($path){
	$firstChar = substr(str_replace('\\','/',$path),0,1);
	if($firstChar != '/'){
		$scriptName = isset($_SERVER['ORIG_SCRIPT_NAME'])?$_SERVER['ORIG_SCRIPT_NAME']:(isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:'');
		// Convert current file path.
		$currentDir = str_replace('\\','/',dirname($scriptName));
		$path = $currentDir . '/' . $path;
	}
	return cmspad_normalize_path($path);
}

// Load system configuration file.
$_CONFIG = array();
$CmspadConfigFile = dirname(__FILE__) . '/config.php';
if(file_exists($CmspadConfigFile)){
	require_once ($CmspadConfigFile);
}
// Load custom configuraiton file.
$CmspadConfigFile = cmspad_relative2absolute('config.php');
if(file_exists($CmspadConfigFile)){
	require_once ($CmspadConfigFile);
}

/**
 * CMSPAD_DEBUG_CONSOLE: Enable javascript console for debugging. false
 */
if(!defined('CMSPAD_DEBUG_CONSOLE')){
	define('CMSPAD_DEBUG_CONSOLE', false);
}
$CMSPAD_CONSTANTS['CMSPAD_DEBUG_CONSOLE'] = CMSPAD_DEBUG_CONSOLE;

/**
 * CMSPAD_PORTLET_ABSPATH: The absulate directory of portlets. CMSPAD_ABSPATH/ptl/
 */
if(!defined('CMSPAD_PORTLET_ABSPATH')){
	define('CMSPAD_PORTLET_ABSPATH',CMSPAD_ABSPATH . 'ptl/');
}
$CMSPAD_CONSTANTS['CMSPAD_PORTLET_ABSPATH'] = CMSPAD_PORTLET_ABSPATH;

/**
 * CMSPAD_PORTLET_RELPATH: The relative directory of portlets. CMSPAD_RELPATH/ptl/
 */
if(!defined('CMSPAD_PORTLET_RELPATH')){
	define('CMSPAD_PORTLET_RELPATH',str_replace('\\','/',str_replace(CMSPAD_ABSPATH,CMSPAD_RELPATH,CMSPAD_PORTLET_ABSPATH)));
}
$CMSPAD_CONSTANTS['CMSPAD_PORTLET_RELPATH'] = CMSPAD_PORTLET_RELPATH;

/**
 * CMSPAD_TEMPORARY_ABSPATH: The system temporary absulate path. CMSPAD_ABSPATH/tmp/
 */
if(!defined('CMSPAD_TEMPORARY_ABSPATH')){
	define('CMSPAD_TEMPORARY_ABSPATH',CMSPAD_ABSPATH . 'tmp/');
}
$CMSPAD_CONSTANTS['CMSPAD_TEMPORARY_ABSPATH'] = CMSPAD_TEMPORARY_ABSPATH;

/**
 * CMSPAD_TEMPORARY_RELPATH: The system temporary relative path. CMSPAD_RELPATH/tmp/
 */
if(!defined('CMSPAD_TEMPORARY_RELPATH')){
	define('CMSPAD_TEMPORARY_RELPATH',str_replace('\\','/',str_replace(CMSPAD_ABSPATH,CMSPAD_RELPATH,CMSPAD_TEMPORARY_ABSPATH)));
}
$CMSPAD_CONSTANTS['CMSPAD_TEMPORARY_RELPATH'] = CMSPAD_TEMPORARY_RELPATH;

/**
 * CMSPAD_TEMPLATE_PATH: The template directory. CMSPAD_ABSPATH/tpl/
 */
if(!defined('CMSPAD_TEMPLATE_PATH')){
	define('CMSPAD_TEMPLATE_PATH',CMSPAD_ABSPATH . 'tpl/');
}
$CMSPAD_CONSTANTS['CMSPAD_TEMPLATE_PATH'] = CMSPAD_TEMPLATE_PATH;

/**
 * CMSPAD_LANGUAGE_PATH: The language directory. CMSPAD_ABSPATH/nls/
 */
if(!defined('CMSPAD_LANGUAGE_PATH')){
	define('CMSPAD_LANGUAGE_PATH',CMSPAD_ABSPATH . 'nls/');
}
$CMSPAD_CONSTANTS['CMSPAD_LANGUAGE_PATH'] = CMSPAD_LANGUAGE_PATH;

/*
 * Check the directory paths.
 */
foreach($CMSPAD_CONSTANTS as $k=>$v){
	if(is_string($v) && substr($v,-1) != '/'){
		trigger_error('CMSPAD Constant "' . $k . '" must end with "/": ' . $v,E_USER_ERROR);
		exit();
	}
}

/**
 * Get parsed template data.
 *
 * @param string $tpl template name.
 * @param array $vars user defined variables. empty array
 * @param array $funcs user defined functions. empty array
 * @return string parsed template data.
 */
function cmspad_template($tpl,$vars = array(),$funcs = array(),$cache = false){
	global $_SESSION,$_SERVER;
	
	cmspad_import('Template');
	$template = new Template(null,null,$cache);
	
	// Set user defined attributes.
	foreach($vars as $varK=>$varV){
		$template->addVariable($varK,$varV);
	}
	
	// Set user defined functions.
	foreach($funcs as $funcK=>$funcV){
		$template->addFunction($funcK,$funcV);
	}
	
	// Load internal variables which are stored in session scope.
	if(isset($_SESSION['cmspad']) && is_array($_SESSION['cmspad'])){
		foreach($_SESSION['cmspad'] as $k=>$v){
			$template->addVariable('Cmspad' . ucfirst($k),$v);
		}
	}
	
	return $template->output($tpl);
}

/**
 * Get parsed template data from portlet.
 *
 * @param string $portlet portlet name.
 * @param string $tpl template name.
 * @param array $vars user defined variables. empty array
 * @param array $funcs user defined functions. empty array
 * @return string parsed template data.
 */
function cmspad_portlet_template($portlet,$tpl,$vars = array(),$funcs = array(),$cache = false){
	global $_SESSION,$_SERVER;
	
	$tplPath = CMSPAD_PORTLET_ABSPATH.$portlet.DIRECTORY_SEPARATOR.'tpl'.DIRECTORY_SEPARATOR;
	$tmpPath = CMSPAD_PORTLET_ABSPATH.$portlet.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR;
	cmspad_import('Template');
	$template = new Template($tplPath,$tmpPath,$cache);
	
	// Set user defined attributes.
	foreach($vars as $varK=>$varV){
		$template->addVariable($varK,$varV);
	}
	
	// Set user defined functions.
	foreach($funcs as $funcK=>$funcV){
		$template->addVariable($funcK,$funcV);
	}
	
	// Load internal variables which are stored in session scope.
	if(isset($_SESSION['cmspad']) && is_array($_SESSION['cmspad'])){
		foreach($_SESSION['cmspad'] as $k=>$v){
			$template->addVariable('Cmspad' . ucfirst($k),$v);
		}
	}
	
	return $template->output($tpl);
}

/**
 * Send email, support Gmail(Need open OpenSSL feature).
 *
 * @return mix Returns true if email was sent successfully.
 *             Returns string if errors occurred.
 */
function cmspad_sendmail($addresses, $title, $content, $attachments = NULL){
	global $_CONFIG;

	$emailClass = cmspad_import("Mailer");
	$mail = new $emailClass();
	$mail->IsSMTP();
	$mail->CharSet = 'utf-8';
	$mail->Encoding = 'base64';

	if(isset($_CONFIG['MAIL']['ADDR'])){
		$mail->From = $_CONFIG['MAIL']['ADDR'];
	}elseif(isset($_CONFIG['SYSTEM']['EMAIL'])){
		$mail->From = $_CONFIG['SYSTEM']['EMAIL'];
	}

	if(isset($_CONFIG['MAIL']['FROM'])){
		$mail->FromName = $_CONFIG['MAIL']['FROM'];
	}elseif(isset($_CONFIG['SYSTEM']['TITLE'])){
		$mail->FromName = $_CONFIG['SYSTEM']['TITLE'];
	}

	if(isset($_CONFIG['MAIL']['UTLS'])){
		$mail->SMTPSecure = $_CONFIG['MAIL']['UTLS'];
	}
	if(isset($_CONFIG['MAIL']['HOST'])){
		$mail->Host = $_CONFIG['MAIL']['HOST'];
	}else{
		$mail->Host = 'localhost';
	}
	if(isset($_CONFIG['MAIL']['PORT'])){
		$mail->Port = $_CONFIG['MAIL']['PORT'];
	}
	if(isset($_CONFIG['MAIL']['USER'])){
		$mail->SMTPAuth = true;
		$mail->Username = $_CONFIG['MAIL']['USER'];
		if(isset($_CONFIG['MAIL']['PSWD'])){
			$mail->Password = $_CONFIG['MAIL']['PSWD'];
		}
	}
	$mail->SetLanguage('zh');

	if(is_array($addresses)){
		foreach($addresses as $address){
			$mail->AddAddress($address);
		}
	}else{
		$mail->AddAddress($addresses);
	}

	$mail->WordWrap = 100;
	$mail->IsHTML(strtolower(strpos($content, 'html')) === false?false:true);
	$mail->Subject = $title;
	$mail->Body = $content;

	if($attachments && is_array($attachments)){
		foreach($attachments as $attachment){
			$mail->AddAttachment($attachment);
		}
	}

	if(!$mail->Send()){
		return $mail->ErrorInfo;
	}else{
		return true;
	}
}

/**
 * Get system database engine
 *
 * @return DatabaseEngine
 */
function cmspad_database(){
	static $de;
	global $_DATABASE;
	if(!isset($de)){
		$declass = cmspad_import('database.DatabaseEngine');
		$de = new $declass(isset($_DATABASE['TYPE'])?$_DATABASE['TYPE']:NULL);
	}
	return $de;
}

/**
 * Get hyperlink from given portlet information.
 *
 * @param string|object $portlet Portlet name or object
 * @param string $method Portlet page name.
 * @param array $params Parameters used in page.
 * @return string the hyperlink generated by above arguments.
 */
function cmspad_hyperlink($portlet = null,$method = null,$params = array()){
	if(!$portlet){
		$portlet = 'DefaultPortal';
	}else if(is_object($portlet)){
		$portlet = get_class($portlet);
	}
	//:20080829
	foreach($params as $k => $v){
		$params[$k] = urlencode($v);
	}
	//:~
	if(isset($GLOBALS['_CMSPAD_DISPATCHER'])){
		$dispatcher = $GLOBALS['_CMSPAD_DISPATCHER'];
		return $dispatcher->hyperlink($portlet,$method,$params);
	}else{
		$url = $_SERVER['SCRIPT_NAME'];
		if($portlet){
			$url .= '/' . $portlet;
			if($method){
				$url .= '/' . $method;
			}else{
				$url .= '/' . $portlet;
			}
			if($params){
				$url .= '/' . implode('/',$params);
			}
		}
		return $url;
	}
}

/**
 * Set system language.
 *
 * @param string $nls Localization name. For example, 'zh-cn','ja-jp'. If the param is empty, then get the default messages from $_COOKIE['CMSPAD_LANGUAGE'].
 * @return bool Returns true if the language file exists.
 */
function cmspad_set_language($nls){
	$nls = cmspad_normalize_path(strtolower($nls));
	$nlsFile = CMSPAD_LANGUAGE_PATH . $nls . '.php';
	if(file_exists($nlsFile)){
		$_SESSION['cmspad']['language'] = $nls;
		return true;
	}else{
		return false;
	}
}

/**
 * Get localized messages.
 *
 * @param string $key The key of localized messages.  
 * @return string|array The localized message. If the key is null, returns all messages.
 */
function cmspad_get_language($key = null){
	static $languages;
	if(!isset($languages)){
		$languages = array();
	}

	$nls = $_SESSION['cmspad']['language'];
	
	// Load localization file.
	if(!isset($languages[$nls])){
		$nlsFile = CMSPAD_LANGUAGE_PATH . $nls . '.php';
		if(file_exists($nlsFile)){
			$_LANGUAGE = array();
			include ($nlsFile);
			$languages[$nls] = $_LANGUAGE;
		}
	}

	if(is_string($key)){
		// Returns single message from key
		return isset($languages[$nls][$key])?$languages[$nls][$key]:'';
	}else{
		// Returns all languages messages.
		return isset($languages[$nls])?$languages[$nls]:array();
	}
}

/**
 * Create directory recursively
 *
 * @param string $path
 * @return bool return true if directory created successfully, otherwise reutrn false.
 */
function cmspad_create_directory($path){
	if($path){
		$path = str_replace('\\','/',$path);
		$dirs = explode('/',trim($path,' /'));
		$tmpPath = substr($path,0,1) == '/'?'/':'';
		foreach($dirs as $dir){
			$tmpPath .= $dir . '/';
			if(!file_exists($tmpPath) || !is_dir($tmpPath)){
				if(!mkdir($tmpPath,0777)){
					return false;
				}
			}
		}
		return true;
	}else{
		return false;
	}
}

/**
 * Remove directory includes flies and sub-directories in it.
 *
 * @param string $dir directory path to removed.
 * @param bool $subonly Only delete sub-files and sub-directories.
 * @return bool return true if directory removed successfully.
 */
function cmspad_remove_directory($dir,$subonly = false){
	$dh = opendir($dir);
	while(($file = readdir($dh))){
		if($file != '.' && $file != '..'){
			$fullpath = $dir . '/' . $file;
			if(!is_dir($fullpath)){
				unlink($fullpath);
			}else{
				cmspad_remove_directory($fullpath);
			}
		}
	}
	closedir($dh);
	if($subonly){
		return true;
	}else{
		return rmdir($dir);
	}
}

// Use default timezone for >= 5.1.0
if(isset($_CONFIG['SYSTEM']['TIMEZONE'])){
	date_default_timezone_set($_CONFIG['SYSTEM']['TIMEZONE']);
}else{
	date_default_timezone_set('Asia/Shanghai');
}

// Search the system language
if(!isset($_SESSION['cmspad']['language'])){
	// Search the browser header to match accepted language
	$acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?$_SERVER['HTTP_ACCEPT_LANGUAGE']:NULL;
	if($acceptLanguage){
		if(strpos($acceptLanguage,';') > 0){
			$alangs = explode(',',substr($acceptLanguage,0,strpos($acceptLanguage,';')));
		}else{
			$alangs = explode(',',$acceptLanguage);
		}
		$_SESSION['cmspad']['language'] = isset($_CONFIG['SYSTEM']['LANGUAGE'])?$_CONFIG['SYSTEM']['LANGUAGE']:'*';
		foreach($alangs as $alang){
			$nlsFile = CMSPAD_LANGUAGE_PATH . $alang . '.php';
			if($nlsFile){
				$_SESSION['cmspad']['language'] = $alang;
				break;
			}
		}
	}
}
?>